home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / think / AmigaGnuChess.lha / chess / src.lha / src / search.c < prev    next >
C/C++ Source or Header  |  1992-09-01  |  35KB  |  1,408 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback
  5.  * Copyright (c) 1992 Free Software Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with GNU Chess; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #include "gnuchess.h"
  24. #ifdef QUIETBACKGROUND
  25. short background = 0;
  26. #endif /* QUIETBACKGROUND */
  27. static short int DepthBeyond;
  28. unsigned short int PrVar[MAXDEPTH];
  29. extern char mvstr[4][6];
  30. #ifdef DEBUG
  31. unsigned short DBLINE[MAXDEPTH];
  32. struct leaf *dbptr;
  33. #endif
  34. struct leaf rootnode;
  35. short int restype;
  36. #include "ataks.h"
  37.  
  38. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  39. inline
  40. void
  41. repetition (short int *cnt)
  42.  
  43. /*
  44.  * Check for draw by threefold repetition.
  45.  */
  46.  
  47. {
  48.   register short i, c;
  49.   register unsigned short m;
  50.   short b[64];
  51.  
  52.   *cnt = c = 0;
  53.   /* try to avoid work */
  54.   if (GameCnt > Game50 + 2)
  55.     {
  56. #ifdef NOMEMSET
  57.       for (i = 0; i < 64; b[i++] = 0) ;
  58. #else
  59.       memset ((char *) b, 0, sizeof (b));
  60. #endif /* NOMEMSET */
  61.       for (i = GameCnt; i >= Game50; i--)
  62.     {
  63.       m = GameList[i].gmove;
  64.       /* does piece exist on diff board? */
  65.       if (b[m & 0xff])
  66.         {
  67.           /* does diffs cancel out, piece back? */
  68.           if ((b[m >> 8] += b[m & 0xff]) == 0)
  69.         --c;
  70.           b[m & 0xff] = 0;
  71.         }
  72.       else
  73.         {
  74.           /* create diff */
  75.           ++c;
  76.           /* does diff cancel out another diff? */
  77.           if (!(b[m >> 8] -= (b[m & 0xff] = board[m & 0xff] +
  78.                   (color[m & 0xff] << 8))))
  79.         --c;;
  80.         }
  81.       /* if diff count is 0 we have a repetition */
  82.       if (c == 0)
  83.         if ((i ^ GameCnt) & 1)
  84.           (*cnt)++;
  85.     }
  86.     }
  87. }
  88.  
  89. int plyscore, globalscore, globalpnt;
  90. void
  91. pick (short int p1, short int p2)
  92.  
  93. /*
  94.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  95.  * move into the p1 element.
  96.  *
  97. */
  98. {
  99.   register struct leaf *p, *q, *r, *k;
  100.   register s0;
  101.   struct leaf temp;
  102.  
  103.   k = p = &Tree[p1];
  104.   q = &Tree[p2];
  105.   s0 = p->score;
  106.   for (r = p + 1; r <= q; r++)
  107.     if ((r->score) > s0)
  108.       {
  109.     s0 = (r->score);
  110.     p = r;
  111.       }
  112.   if (p != k)
  113.     {
  114.       temp = *p;
  115.       *p = *k;
  116.       *k = temp;
  117.     }
  118. }
  119. #ifdef DEBUG40
  120.   int d7flag;
  121. #endif
  122.  
  123. static int TCcount, TCleft;
  124. void
  125. SelectMove (short int side, short int iop)
  126.  
  127.  
  128. /*
  129.  * Select a move by calling function search() at progressively deeper ply
  130.  * until time is up or a mate or draw is reached. An alpha-beta window of
  131.  * -Awindow to +Bwindow points is set around the score returned from the
  132.  * previous iteration. If Sdepth != 0 then the program has correctly
  133.  * predicted the opponents move and the search will start at a depth of
  134.  * Sdepth+1 rather than a depth of 1.
  135.  */
  136.  
  137. {
  138.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  139.   static short int alpha, beta, score;
  140.   static struct GameRec *g;
  141.   int bookflag = false;
  142.   int Jscore;
  143.   unsigned short tmp[MAXDEPTH];
  144.   flag.timeout = false;
  145.   flag.musttimeout = false;
  146.   xside = side ^ 1;
  147. #ifdef DEBUG40
  148.     d7flag = 0;
  149. #endif
  150.   /* if background mode set to infinite */
  151.   if (iop == 2)
  152.     {
  153.       ResponseTime = 9999999;
  154. #ifdef QUIETBACKGROUND
  155.       background = true;
  156. #endif /* QUIETBACKGROUND */
  157.     }
  158.   else
  159.     {
  160.       player = side;
  161.       if (TCflag)
  162.     {
  163.       TCcount = 0;
  164. #ifdef QUIETBACKGROUND
  165.       background = false;
  166. #endif /* QUIETBACKGROUND */
  167.       if (TimeControl.moves[side] < 1)
  168.         TimeControl.moves[side] = 1;
  169.       /* special case time per move specified */
  170.       if (flag.onemove)
  171.         {
  172.           ResponseTime = TimeControl.clock[side] - 100;
  173.           TCleft = 0;
  174.         }
  175.       else
  176.         {
  177.           /* calculate avg time per move remaining */
  178.           ResponseTime = (TimeControl.clock[side] ) / (((TimeControl.moves[side]) *3));
  179.               TCleft = ResponseTime>>1;
  180.            if (TimeControl.moves[side] < 5) TCcount = MAXTCCOUNT - 1;
  181.         }
  182.       if (ResponseTime < 100)
  183.         {
  184.           ResponseTime = 100;
  185.           TCcount = MAXTCCOUNT;
  186.         }
  187.       else if (ResponseTime < 200)
  188.         {
  189.           TCcount = MAXTCCOUNT - 1;
  190.         }
  191.     }
  192.       else
  193.         ResponseTime = MaxResponseTime;
  194.       if(TCleft){TCcount = ((TimeControl.clock[side] - ResponseTime)/2)/TCleft;
  195.       if(TCcount > MAXTCCOUNT)TCcount = 0; else TCcount = MAXTCCOUNT - TCcount;}
  196.     else TCcount = MAXTCCOUNT;
  197.     }
  198.  
  199.   ExtraTime = 0;
  200.   ExaminePosition ();
  201.   score = ScorePosition (side);
  202. #ifdef QUIETBACKGROUND
  203.   if (!background)
  204. #endif /* QUIETBACKGROUND */
  205.     ShowSidetoMove ();
  206. #ifdef notdef
  207.   if (TCflag && TCcount < MAXTCCOUNT)
  208.     if (score < SCORETIME)
  209.       {
  210.     ExtraTime += TCleft;
  211.     TCcount++;
  212.       }
  213. #endif
  214.  
  215. #ifdef QUIETBACKGROUND
  216.   if (!background)
  217. #endif /* QUIETBACKGROUND */
  218.     SearchStartStuff (side);
  219. #ifdef HISTORY
  220. #ifdef NOMEMSET
  221.   for (i = 0; i < 32768; i++)
  222.     history[i] = 0;
  223. #else
  224.   memset ((char *) history, 0, sizeof (history));
  225. #endif /* NOMEMSET */
  226. #endif
  227.   FROMsquare = TOsquare = -1;
  228.   PV = 0;
  229.   if (iop == 1)
  230.     hint = 0;
  231.   for (i = 0; i < MAXDEPTH; i++)
  232.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  233.   /* set initial window for search */
  234.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  235.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  236.   rpt = 0;
  237.   TrPnt[1] = 0;
  238.   root = &Tree[0];
  239.   MoveList (side, 1);
  240.   for (i = TrPnt[1]; i < TrPnt[2]; i++) pick (i, TrPnt[2] - 1);
  241.   /* can I get a book move? */
  242.   if (flag.regularstart && Book){    
  243.     flag.timeout = bookflag = OpeningBook (&hint, side);
  244.     if (TCflag) ResponseTime += ResponseTime;
  245.   }
  246.   rootnode = Tree[0];
  247.   /* zero stats for hash table */
  248.   reminus = replus = 0;
  249.   NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  250.   globalscore = plyscore = score;
  251. #ifdef DEBUG4
  252.   if (debuglevel & 8)
  253.     {
  254.       int j;
  255.       for (j = 1; j < 2; j++)
  256.     {
  257.       int idb;
  258.       for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  259.         {
  260.           algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  261.           printf ("level 8 %d-->%d %s %d %d\n", j, idb, mvstr[0], Tree[idb].score, Tree[idb].width);
  262.         }
  263.     }
  264.     }
  265. #endif
  266.  
  267. /********************* main loop ********************************/
  268.   while (!flag.timeout)
  269.     {
  270.       /* go down a level at a time */
  271.       Sdepth++;
  272.       DepthBeyond = Sdepth + ((Sdepth == 1) ? (DEPTHBEYOND >> 1) : DEPTHBEYOND);
  273.  
  274. #if !defined CHESSTOOL
  275. #ifdef QUIETBACKGROUND
  276.       if (!background)
  277. #endif /* QUIETBACKGROUND */
  278.     ShowDepth (' ');
  279. #endif
  280.       /* search at this level returns score of PV */
  281.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  282.       /* save PV as killer */
  283.       for (i = 1; i <= Sdepth; i++)
  284.     killr0[i] = PrVar[i];
  285.  
  286.       /* low search failure re-search with (-inf,score) limits  */
  287.       if (score < alpha)
  288.     {
  289.       reminus++;
  290. #ifdef QUIETBACKGROUND
  291.       if (!background)
  292. #endif /* QUIETBACKGROUND */
  293.         ShowDepth ('-');
  294.       if (TCflag && TCcount < MAXTCCOUNT)
  295.         {
  296.           TCcount = MAXTCCOUNT-1;
  297.           ExtraTime += (6*TCleft);
  298.         }
  299.       score = search (side, 1, Sdepth, -9999, score, PrVar, &rpt);
  300.     }
  301.  
  302.       /* high search failure re-search with (score, +inf) limits */
  303.       if (score > beta && !(root->flags & exact))
  304.     {
  305.       replus++;
  306. #ifdef QUIETBACKGROUND
  307.       if (!background)
  308. #endif /* QUIETBACKGROUND */
  309.         ShowDepth ('+');
  310.       score = search (side, 1, Sdepth, score, 9999, PrVar, &rpt);
  311.     }
  312. /**************** out of search ********************************************/
  313.       if (Sdepth == MaxSearchDepth)
  314.     flag.timeout = true;
  315.  
  316.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNT))
  317.     {
  318.       if (tmp[1] != PrVar[1] || tmp[2] != PrVar[2])
  319.         {
  320.           TCcount++;
  321.           ExtraTime += TCleft;
  322.         }
  323.  
  324.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  325.         {
  326.           TCcount++;
  327.           ExtraTime += TCleft;
  328.         }
  329.     }
  330.       if(TCflag) if ((4 * et) > (2 * ResponseTime + ExtraTime)) flag.timeout = true;
  331. /************************ time control ***********************************/
  332.  
  333.       /* save PV as killer */
  334.       for (i = 1; i <= Sdepth + 1; i++)
  335.     killr0[i] = PrVar[i];
  336.       if (((rootnode.f << 8) | rootnode.t) != PrVar[1])
  337.     {
  338.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  339.         if (((Tree[i].f << 8) | Tree[i].t) == PrVar[1])
  340.           {
  341.         rootnode = Tree[i];
  342.         break;
  343.           }
  344.     }
  345.       for (i = 1; i <= Sdepth + 1; i++)
  346.     tmp[i] = PrVar[i];
  347.       if(!flag.timeout)Tscore[0] = score;
  348.       /*if (!flag.timeout)*/
  349.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  350.     pick (i, TrPnt[2] - 1);
  351.       /* if done or nothing good to look at quit */
  352.       if ((rootnode.flags & exact) || (score < -9000))
  353.     flag.timeout = true;
  354. #ifdef DEBUG13
  355.       if (flag.timeout && !background)
  356.     {
  357.       FILE *D;
  358.       int r, c, l;
  359.       struct leaf *xnode;
  360.       D = fopen ("/tmp/DEBUG", "a+");
  361.       fprintf (D, " %d ply %d sco %d TC %d rs %d gl %d cnt %d\n",
  362.            Sdepth, plyscore, score, TCcount, restype,
  363.            globalpnt, TrPnt[2] - TrPnt[1]);
  364.       for (i = 1; tmp[i]; i++)
  365.         {
  366.           algbr (tmp[i] >> 8, tmp[i] & 0xff, 0);
  367.           fprintf (D, "%s ", mvstr[0]);
  368.         }
  369.       fprintf (D, "\n");
  370.       for (i = 1; PrVar[i]; i++)
  371.         {
  372.           algbr (PrVar[i] >> 8, PrVar[i] & 0xff, 0);
  373.           fprintf (D, "%s ", mvstr[0]);
  374.         }
  375.       fprintf (D, "\n");
  376.       algbr (rootnode.f, rootnode.t, rootnode.flags);
  377.       fprintf (D, "%s ", mvstr[0]);
  378.       fprintf (D, "\n");
  379.       fclose (D);
  380.     }
  381. #endif
  382.       /* find the next best move put below root */
  383.       if (!flag.timeout)
  384.     {
  385.       /* */
  386. #if !defined NODYNALPHA
  387.       Jscore = (plyscore + score) >> 1;
  388. #endif
  389.       plyscore = score;
  390.       /* recompute search window */
  391.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  392. #if !defined NODYNALPHA
  393.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - abs (Jscore / 12) - 20;
  394. #else
  395.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  396. #endif
  397.     }
  398.       else
  399.     for (i = 1; i <= Sdepth + 1; i++)
  400.       PrVar[i] = tmp[i];
  401. #if !defined CHESSTOOL
  402. #ifdef QUIETBACKGROUND
  403.       if (!background)
  404. #endif /* QUIETBACKGROUND */
  405.     ShowResults (score, PrVar, '.');
  406. #endif
  407. #ifdef DEBUG4
  408.       if (debuglevel & 16)
  409.     {
  410.       int j;
  411.       printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage);
  412.       for (j = 1; j < 2; j++)
  413.         {
  414.           int idb;
  415.           for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  416.         {
  417.           algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  418.           printf ("level 16 %d-->%d %s %d %d %x\n", Sdepth, idb, mvstr[0], Tree[idb].score, Tree[idb].width, Tree[idb].flags);
  419.         }
  420.         }
  421.     }
  422. #endif
  423.  
  424.     }
  425. /******************************* end of main loop ***********************************/
  426.   /* background mode */
  427.   if (iop == 2)
  428.     return;
  429. #ifdef DEBUG4
  430.   if (debuglevel & 4)
  431.     {
  432.       int j;
  433.       printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage);
  434.       for (j = 1; j < 2; j++)
  435.     {
  436.       int idb;
  437.       for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  438.         {
  439.           algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  440.           printf ("level 4 %d-->%d %s %d %d\n", j, idb, mvstr[0], Tree[idb].score, Tree[idb].width);
  441.         }
  442.     }
  443.     }
  444. #endif
  445.  
  446.   if (rpt >= 2)
  447.     {
  448.       rootnode.flags |= draw;
  449.       DRAW = CP[101];        /*Repetition*/
  450.     }
  451.   else
  452.     /* if no moves and not in check then draw */
  453.   if ((rootnode.score == -9999) && !(SqAtakd (PieceList[side][0], xside)))
  454.     {
  455.       rootnode.flags |= draw;
  456.       DRAW = CP[87];        /*No moves*/
  457.     }
  458.   else if (GameCnt == MAXMOVES)
  459.     {
  460.       rootnode.flags |= draw;
  461.       DRAW = CP[80];        /*Max Moves*/
  462.     }
  463.  
  464.   /* not in book so set hint to guessed move for other side */
  465.   if (!bookflag)
  466.     hint = ((tmp[1]) ? tmp[2] : 0);
  467.  
  468.   /* if not mate or draw make move and output it */
  469.   if (((score > -9999) && (rpt <= 2)) || (rootnode.flags & draw))
  470.     {
  471.       MakeMove (side, &rootnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  472. #if !defined NOMATERIAL
  473.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  474.     {
  475.       rootnode.flags |= draw;
  476.       DRAW = CP[224];    /*No pieces*/
  477.     }
  478.       else
  479. #endif
  480.       if (!PieceCnt[black] && !PieceCnt[white])
  481.     {
  482.       rootnode.flags |= draw;
  483.       DRAW = CP[88];    /*No pieces*/
  484.     }
  485.       algbr (rootnode.f, rootnode.t, (short) rootnode.flags);
  486.     }
  487.   else {
  488.     algbr (0, 0, 0);        /* Zero move string when mate. */
  489.     rootnode.score = score;    /* When mate, ignore distinctions! --SMC */
  490.   }
  491.   g = &GameList[GameCnt];
  492.   if(g->flags & capture && g->piece == king)
  493.     {flag.mate = flag.illegal = true;}
  494.   /* If Time Control get the elapsed time */
  495.   if (TCflag)
  496.     ElapsedTime (1);
  497.   OutputMove ();
  498.   /* if mate set flag */
  499.   if ((score == -9999 || score == 9998) )
  500.     flag.mate = true;
  501.   /* if mate clear hint */
  502.   if (flag.mate)
  503.     hint = 0;
  504.   /* if pawn move or capture or castle or promote zero repitition array */
  505.   if ((board[rootnode.t] == pawn) || (rootnode.flags & (capture | cstlmask | promote)))
  506.     {
  507.       Game50 = GameCnt;
  508.       ZeroRPT ();
  509.     }
  510.   /* add move to game list */
  511.   g->score = score;
  512.   g->nodes = NodeCnt;
  513.   g->time =  et;
  514.   g->depth = Sdepth;
  515. #ifdef DEBUG40
  516.   g->d1 = TCcount;
  517.   g->d2 = ResponseTime ;
  518.   g->d3 = ExtraTime;
  519.   g->d4 = TCleft;
  520.   g->d5 = et;
  521.   g->d6 = TimeControl.clock[side];
  522.   g->d7 = d7flag;
  523. #endif
  524.   /* update time comtrol info */
  525.   if (TCflag)
  526.     {
  527. #if defined CHESSTOOL || defined XBOARD
  528.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  529. #else
  530.       TimeControl.clock[side] -= (et + OperatorTime);
  531. #endif
  532.       /* finished our required moves - setup the next set */
  533.       if (--TimeControl.moves[side] == 0)
  534.     {
  535.       if (XC)
  536.         if (XCmore < XC)
  537.           {
  538.         TCmoves = XCmoves[XCmore];
  539.         TCminutes = XCminutes[XCmore];
  540.         TCseconds = XCseconds[XCmore];
  541.         XCmore++;
  542.           }
  543.       SetTimeControl ();
  544.     }
  545.     }
  546.   /* check for end conditions */
  547.   if ((rootnode.flags & draw) /*&& flag.bothsides*/ )
  548.      flag.mate = true;
  549.   else if (GameCnt == MAXMOVES)
  550.     {
  551.       flag.mate = true;
  552.     }
  553.   /* out of move store, you loose */
  554.   else
  555.     /* switch to other side */
  556.     player = xside;
  557.   Sdepth = 0;
  558. }
  559.  
  560. short
  561. search (short int side,
  562.     register short int ply,
  563.     register short int depth,
  564.     short int alpha,
  565.     short int beta,
  566.     unsigned short  int *bstline,
  567.     short int *rpt)
  568.  
  569. /*
  570.  * Perform an alpha-beta search to determine the score for the current board
  571.  * position. If depth <= 0 only capturing moves, pawn promotions and
  572.  * responses to check are generated and searched, otherwise all moves are
  573.  * processed. The search depth is modified for check evasions, certain
  574.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  575.  * the nominal search depth.
  576.  */
  577.  
  578.  
  579. {
  580.   register short j, pnt;
  581.   short tempb, tempc, tempsf, tempst, cf;
  582.   short xside, pbst, score, rcnt, slk, InChk;
  583.   unsigned short mv, nxtline[MAXDEPTH];
  584.   struct leaf *node, tmp;
  585.   short best;
  586.   short bestwidth = 0;
  587.  
  588.   NodeCnt++;
  589.   /* look every ZNODE nodes for a timeout */
  590.   if (TCflag || MaxResponseTime)
  591.     {
  592.       if (NodeCnt > ETnodes)
  593.     {
  594.       ElapsedTime (2);
  595.       if (Sdepth > MINDEPTH && flag.musttimeout)
  596.         {
  597.           flag.timeout = true;
  598.           flag.musttimeout = false;
  599.         }
  600.       else if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH)
  601.                {/* try to extend to finish ply */
  602.                 if (TCflag && TCcount < MAXTCCOUNT)
  603.                          { TCcount += 1; ExtraTime += TCleft; 
  604. #ifdef DEBUG40
  605.         d7flag++;
  606. #endif
  607.                }
  608.                 else flag.timeout = true;
  609.                }
  610.     }
  611.  
  612.     }
  613.   else if (flag.musttimeout && Sdepth > MINDEPTH)
  614.     {
  615.       flag.timeout = true;
  616.       flag.musttimeout = false;
  617.     }
  618.  
  619.   xside = side ^ 1;
  620.   /* slk is lone king indicator for either side */
  621.   score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  622.  
  623.   /*
  624.    * check for possible repitition if so call repitition - rpt is repeat
  625.    * count
  626.    */
  627.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  628.     {
  629.       repetition (rpt);
  630.  
  631.       /*
  632.        * repeat position >2 don't need to return score it's taken care of
  633.        * above
  634.        */
  635.       if (*rpt == 1 )  score /= 2;
  636.     }
  637.   else
  638.     *rpt = 0;
  639.  
  640.   /* score > 9000 its a draw or mate */
  641.   if (score > 9000)
  642.     {
  643.       bstline[ply] = 0;
  644. #if defined(AMIGADB) && defined(LATTICE)
  645.     {
  646.       if (abs(score) >= 10000)
  647.     flash(),fprintf(stderr, "search1: score = %d\n", score);
  648.       return (score);
  649.     }
  650. #else
  651.       return (score);
  652. #endif
  653.     }
  654.   /* Do we need to add depth because of special conditions */
  655.   /* if in check or pawn threat or in capture sequence search deeper */
  656. /*************************************** depth extensions ***********************************/
  657.   if (depth > 0)
  658.     {
  659.       /* Allow opponent a chance to check again */
  660.       if (InChk)
  661.     depth = (depth < 2) ? 2 : depth;
  662.       else if (PawnThreat[ply - 1] ||
  663.            (flag.rcptr && (score > alpha) &&
  664.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  665.     ++depth;
  666.     }
  667.   else
  668.     {
  669.       if (score >= alpha &&
  670.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  671.     depth = 1;
  672.       else if (score <= beta &&
  673.            ((ply < Sdepth + 4) && (ply > 4) &&
  674.         ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  675.         ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  676.     depth = 1;
  677.     }
  678. /*******************************************************************************************/
  679.   /* try the local transition table if it's there */
  680. #if ttblsz
  681.   if (flag.hash && ply > 1)
  682.     {
  683.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  684.     {
  685.       bstline[ply] = PV;
  686.       bstline[ply + 1] = 0;
  687. #ifdef DEBUG4
  688.       if (debuglevel & 64)
  689.         {
  690.           algbr (PV >> 8, PV & 0xff, 0);
  691.           printf ("-get-> d=%d s=%d p=%d a=%d b=%d %s\n", depth, score, ply, alpha, beta, mvstr[0]);
  692.         }
  693. #endif
  694.       if (beta == -20000)
  695. #if defined(AMIGADB) && defined(LATTICE)
  696.     {
  697.       if (abs(score) >= 10000)
  698.     flash(),fprintf(stderr, "search2: score = %d\n", score);
  699.       return (score);
  700.     }
  701. #else
  702.       return (score);
  703. #endif
  704.       if (alpha > beta)
  705. #if defined(AMIGADB) && defined(LATTICE)
  706.     {
  707.       if (abs(alpha) >= 10000)
  708.     flash(),fprintf(stderr, "search3: alpha = %d\n", alpha);
  709.       return (alpha);
  710.     }
  711. #else
  712.         return (alpha);
  713. #endif
  714.     }
  715. #ifdef HASHFILE
  716.       /* ok try the transition file if its there */
  717.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  718.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  719.     {
  720.       int hgood = false;
  721.       int f = PV >> 8;
  722.       int t = PV & 0x3f;
  723.       register int i;
  724.       /*
  725.            * if you find something put it in the local table for future
  726.            * reference
  727.            */
  728.       hgood = false;
  729.       for (i = TrPnt[ply]; i < TrPnt[ply + 1]; i++)
  730.         {
  731.           if (Tree[i].f == f && Tree[i].t == t)
  732.         {
  733.           hgood = true;
  734.           break;
  735.         }
  736.         }
  737.       if (hgood)
  738.         {
  739.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  740.           bstline[ply] = PV;
  741.           bstline[ply + 1] = 0;
  742.           if (beta == -20000)
  743. #if defined(AMIGADB) && defined(LATTICE)
  744.     {
  745.       if (abs(score) >= 10000)
  746.     flash(),fprintf(stderr, "search4: score = %d\n", score);
  747.       return (score);
  748.     }
  749. #else
  750.       return (score);
  751. #endif
  752.           if (alpha > beta)
  753. #if defined(AMIGADB) && defined(LATTICE)
  754.     {
  755.       if (abs(alpha) >= 10000)
  756.     flash(),fprintf(stderr, "search5: alpha = %d\n", alpha);
  757.       return (alpha);
  758.     }
  759. #else
  760.         return (alpha);
  761. #endif
  762.         }
  763. #ifdef DEBUG10
  764.       else
  765.         {
  766.           FILE *D;
  767.           int r, c, l;
  768.           struct leaf *xnode;
  769.           D = fopen ("/tmp/DEBUG", "w");
  770.           pnt = TrPnt[2];
  771.           fprintf (D, "hashfile failure\n");
  772.           algbr (PV >> 8, PV & 0x3f, 0);
  773.           fprintf (D, "inout move is %s\n", mvstr);
  774.           fprintf (D, "legal move are \n");
  775.           for (r = TrPnt[ply]; r < TrPnt[ply + 1]; r++)
  776.         {
  777.           xnode = &Tree[r];
  778.           algbr (xnode->f, xnode->t, (short) xnode->flags);
  779.           fprintf (D, "%s %s %s %s\n", mvstr[0], mvstr[1], mvstr[2], mvstr[3]);
  780.         }
  781.           fprintf (D, "\n current board is\n");
  782.           for (r = 7; r >= 0; r--)
  783.         {
  784.           for (c = 0; c <= 7; c++)
  785.             {
  786.               l = locn (r, c);
  787.               if (color[l] == neutral)
  788.             fprintf (D, " -");
  789.               else if (color[l] == white)
  790.             fprintf (D, " %c", qxx[board[l]]);
  791.               else
  792.             fprintf (D, " %c", pxx[board[l]]);
  793.             }
  794.           fprintf (D, "\n");
  795.         }
  796.           fprintf (D, "\n");
  797.           fclose (D);
  798.         }
  799. #endif
  800.     }
  801. #endif /* HASHFILE */
  802.     }
  803.  
  804. #endif /* ttblsz */
  805.  
  806.   /*
  807.    * if more then DepthBeyond ply past goal depth or at goal depth and
  808.    * score > beta quit - means we are out of the window
  809.    */
  810.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  811.     {
  812. #if defined(AMIGADB) && defined(LATTICE)
  813.     {
  814.       if (abs(score) >= 10000)
  815.     flash(),fprintf(stderr, "search6: score = %d\n", score);
  816.       return (score);
  817.     }
  818. #else
  819.       return (score);
  820. #endif
  821.     }
  822.  
  823.   /*
  824.    * if below first ply and not at goal depth generate all moves else only
  825.    * capture moves
  826.    */
  827.   if (ply > 1)
  828.     if (depth > 0)
  829.       {
  830.     MoveList (side, ply);
  831.       }
  832.     else
  833.       CaptureList (side, ply);
  834.  
  835.   /* no moves return what we have */
  836.  
  837.   /*
  838.    * normally a search will continue til past goal and no more capture
  839.    * moves exist
  840.    */
  841.   /* unless it hits DepthBeyond */
  842.   if (TrPnt[ply] == TrPnt[ply + 1])
  843.     {
  844. #if defined(AMIGADB) && defined(LATTICE)
  845.     {
  846.       if (abs(score) >= 10000)
  847.     flash(),fprintf(stderr, "search7: score = %d\n", score);
  848.       return (score);
  849.     }
  850. #else
  851.       return (score);
  852. #endif
  853.     }
  854.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  855.  
  856.   /* if not at goal set best = -inf else current score */
  857.   best = ((depth > 0) ? -12000 : score);
  858.   /* if best so far is better than alpha set alpha to best */
  859.   if (best > alpha)
  860.     alpha = best;
  861.   /********************** main loop ************************************************************************/
  862.   /* look at each move until no more or beta cutoff */
  863.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  864.     {
  865.       /* find the most interesting looking of the remaining moves */
  866.       pick (pnt, TrPnt[ply + 1] - 1);
  867.  
  868.       node = &Tree[pnt];
  869.       /* is this a forbidden move */
  870.       if (ply == 1 && node->score == -32768)
  871.     continue;
  872.       nxtline[ply + 1] = 0;
  873.       if (cf && score + node->score < alpha)
  874.     break;
  875. #if !defined CHESSTOOL
  876.       /* if at top level */
  877.       if (ply == 1)
  878.     {            /* at the top update search status */
  879.       if (flag.post)
  880. #ifdef QUIETBACKGROUND
  881.         if (!background)
  882. #endif /* QUIETBACKGROUND */
  883.           ShowCurrentMove (pnt, node->f, node->t);
  884.     }
  885. #endif
  886.       if (!(node->flags & exact))
  887.     {
  888.       /* make the move and go deeper */
  889.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  890.       CptrFlag[ply] = (node->flags & capture);
  891.       PawnThreat[ply] = (node->flags & pwnthrt);
  892.       Tscore[ply] = node->score;
  893.       PV = node->reply;
  894.       node->score = -search (xside, ply + 1,
  895.                  ((depth > 0) ? depth - 1 : 0),
  896.                  -beta, -alpha,
  897.                  nxtline, &rcnt);
  898.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  899.       if (abs (node->score) > 9000)
  900.         node->flags |= exact;
  901.       else if (rcnt == 1) node->score /= 2;
  902.       if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  903.         {
  904.           node->flags |= (draw | exact);
  905.           DRAW = CP[58];    /* Draw */
  906.           node->score = ((side == computer) ? contempt : -contempt);
  907.         }
  908.       node->reply = nxtline[ply + 1];
  909.       /* reset to try next move */
  910.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  911.     }
  912.       /* if best move so far */
  913.  
  914.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  915.     {
  916.       /* all things being equal pick the denser part of the tree */
  917.       bestwidth = node->width;
  918.  
  919.       /*
  920.            * if not at goal depth and better than alpha and not an exact
  921.            * score increment by depth
  922.            */
  923.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  924.         node->score += depth;
  925.       best = node->score;
  926.       pbst = pnt;
  927.       if (best > alpha)
  928.         {
  929.           alpha = best;
  930.         }
  931.       /* update best line */
  932.       for (j = ply + 1; nxtline[j] > 0; j++)
  933.         bstline[j] = nxtline[j];
  934.       bstline[j] = 0;
  935.       bstline[ply] = (node->f << 8) | node->t;
  936.       /* if at the top */
  937.       if (ply == 1)
  938.         {
  939.  
  940.           /*
  941.                * if its better than the root score make it the root
  942.                */
  943.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  944.         {
  945.           tmp = Tree[pnt];
  946.           for (j = pnt - 1; j >= 0; j--)
  947.             Tree[j + 1] = Tree[j];
  948.           Tree[0] = tmp;
  949.           pbst = 0;
  950.         }
  951. #if !defined CHESSTOOL
  952. #ifdef QUIETBACKGROUND
  953.           if (!background)
  954. #endif /* QUIETBACKGROUND */
  955.         if (Sdepth > 2)
  956.           if (best > beta)
  957.             {
  958.               ShowResults (best, bstline, '+');
  959.             }
  960.           else if (best < alpha)
  961.             {
  962.               ShowResults (best, bstline, '-');
  963.             }
  964.           else
  965.             ShowResults (best, bstline, '&');
  966. #endif
  967.           restype = (best < alpha) ? false : true;
  968.         }
  969.     }
  970.       if (Sdepth > MINDEPTH && flag.timeout)
  971.     {
  972.       if (ply == 1)
  973.         globalpnt = (pnt);
  974. #if defined(AMIGADB) && defined(LATTICE)
  975.     {
  976.       if (abs(Tscore[ply - 1]) >= 10000)
  977.     flash(),fprintf(stderr, "search8: Tscore[ply - 1] = %d\n", Tscore[ply - 1]);
  978.       return (Tscore[ply - 1]);
  979.     }
  980. #else
  981.       return (Tscore[ply - 1]);
  982. #endif
  983.     }
  984.     }
  985.  
  986.   /******************************************************************************************/
  987.   globalpnt = (pnt);
  988.   node = &Tree[pbst];
  989.   mv = (node->f << 8) | node->t;
  990.  
  991.   /*
  992.    * we have a move so put it in local table - if it's already there done
  993.    * else if not there or needs to be updated also put it in hashfile
  994.    */
  995. #if ttblsz
  996.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  997.     {
  998.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  999. #ifdef HASHFILE
  1000.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1001.     {
  1002.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1003.     }
  1004. #else
  1005.     );
  1006. #endif /* HASHFILE */
  1007.     }
  1008.  
  1009. #endif /* ttblsz */
  1010.   if (depth > 0)
  1011.     {
  1012. #ifdef HISTORY
  1013.       j = (node->f << 6) | node->t;
  1014.       if (side == black)
  1015.     j |= 0x4000;
  1016.       if (history[j] < HISTORYLIM)
  1017.     history[j] += (unsigned char) depth << 1;
  1018. #endif
  1019.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1020.     if (best <= beta)
  1021.       killr3[ply] = mv;
  1022.     else if (mv != killr1[ply])
  1023.       {
  1024.         killr2[ply] = killr1[ply];
  1025.         killr1[ply] = mv;
  1026.       }
  1027.       killr0[ply] = ((best > 9000) ? mv : 0);
  1028.     }
  1029.  
  1030. #if defined(AMIGADB) && defined(LATTICE)
  1031.     {
  1032.       if (abs(best) >= 10000)
  1033.     flash(),fprintf(stderr, "search9: best = %d\n", best);
  1034.       return (best);
  1035.     }
  1036. #else
  1037.       return (best);
  1038. #endif
  1039. }
  1040.  
  1041.  
  1042.  
  1043.  
  1044. int
  1045. castle (short int side, short int kf, short int kt, short int iop)
  1046.  
  1047. /* Make or Unmake a castling move. */
  1048.  
  1049. {
  1050.   register short rf, rt, t0, xside;
  1051.  
  1052.   xside = side ^ 1;
  1053.   if (kt > kf)
  1054.     {
  1055.       rf = kf + 3;
  1056.       rt = kt - 1;
  1057.     }
  1058.   else
  1059.     {
  1060.       rf = kf - 4;
  1061.       rt = kt + 1;
  1062.     }
  1063.   if (iop == 0)
  1064.     {
  1065.       if (kf != kingP[side] ||
  1066.       board[kf] != king ||
  1067.       board[rf] != rook ||
  1068.       color[kf] != side ||
  1069.       color[rf] != side ||
  1070.       Mvboard[kf] != 0 ||
  1071.       Mvboard[rf] != 0 ||
  1072.       color[kt] != neutral ||
  1073.       color[rt] != neutral ||
  1074.       color[kt - 1] != neutral ||
  1075.       SqAtakd (kf, xside) ||
  1076.       SqAtakd (kt, xside) ||
  1077.       SqAtakd (rt, xside))
  1078.     return (false);
  1079.     }
  1080.   else
  1081.     {
  1082.       if (iop == 1)
  1083.     {
  1084.       castld[side] = true;
  1085.       Mvboard[kf]++;
  1086.       Mvboard[rf]++;
  1087.     }
  1088.       else
  1089.     {
  1090.       castld[side] = false;
  1091.       Mvboard[kf]--;
  1092.       Mvboard[rf]--;
  1093.       t0 = kt;
  1094.       kt = kf;
  1095.       kf = t0;
  1096.       t0 = rt;
  1097.       rt = rf;
  1098.       rf = t0;
  1099.     }
  1100.       board[kt] = king;
  1101.       color[rt] = color[kt] = side;
  1102.       Pindex[kt] = 0;
  1103.       board[kf] = no_piece;
  1104.       color[rf] = color[kf] = neutral;
  1105.       board[rt] = rook;
  1106.       Pindex[rt] = Pindex[rf];
  1107.       board[rf] = no_piece;
  1108.       PieceList[side][Pindex[kt]] = kt;
  1109.       PieceList[side][Pindex[rt]] = rt;
  1110.       UpdateHashbd (side, king, kf, kt);
  1111.       UpdateHashbd (side, rook, rf, rt);
  1112.     }
  1113.   return (true);
  1114. }
  1115.  
  1116.  
  1117. void
  1118. EnPassant (short int xside, short int f, short int t, short int iop)
  1119.  
  1120. /*
  1121.  * Make or unmake an en passant move.
  1122.  */
  1123.  
  1124. {
  1125.   register short l;
  1126.  
  1127.   l = t + ((t > f) ? -8 : 8);
  1128.   if (iop == 1)
  1129.     {
  1130.       board[l] = no_piece;
  1131.       color[l] = neutral;
  1132.     }
  1133.   else
  1134.     {
  1135.       board[l] = pawn;
  1136.       color[l] = xside;
  1137.     }
  1138.   InitializeStats ();
  1139.   if (iop != 1)
  1140.     epsquare = t;
  1141. }
  1142.  
  1143.  
  1144. void
  1145. UpdatePieceList (short int side, short int sq, short int iop)
  1146.  
  1147. /*
  1148.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1149.  * capture is unmade.
  1150.  */
  1151.  
  1152. {
  1153.   register short i;
  1154.  
  1155.   if (iop == 1)
  1156.     {
  1157.       PieceCnt[side]--;
  1158.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1159.     {
  1160.       PieceList[side][i] = PieceList[side][i + 1];
  1161.       Pindex[PieceList[side][i]] = i;
  1162.     }
  1163.     }
  1164.   else
  1165.     {
  1166.       PieceCnt[side]++;
  1167.       PieceList[side][PieceCnt[side]] = sq;
  1168.       Pindex[sq] = PieceCnt[side];
  1169.     }
  1170. }
  1171.  
  1172. void
  1173. MakeMove (short int side,
  1174.       struct leaf * node,
  1175.       short int *tempb,    /* color of to square */
  1176.       short int *tempc,    /* piece at to square */
  1177.       short int *tempsf,    /* static value of piece on from */
  1178.       short int *tempst,    /* static value of piece on to */
  1179.       short int *INCscore)    /* score increment for pawn structure change */
  1180.  
  1181. /*
  1182.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1183.  * position obtained after making the move pointed to by node. Also update
  1184.  * miscellaneous stuff that changes when a move is made.
  1185.  */
  1186.  
  1187. {
  1188.   register short f, t, xside, ct, cf;
  1189.   register struct GameRec *g;
  1190.  
  1191.   xside = side ^ 1;
  1192.   g = &GameList[++GameCnt];
  1193.   g->hashkey = hashkey;
  1194.   g->hashbd = hashbd;
  1195.   f = node->f;
  1196.   t = node->t;
  1197.   epsquare = -1;
  1198.   FROMsquare = f;
  1199.   TOsquare = t;
  1200.   *INCscore = 0;
  1201.   g->Game50 = Game50;
  1202.   g->gmove = (f << 8) | t;
  1203.   g->flags = node->flags;
  1204.   if (node->flags & cstlmask)
  1205.     {
  1206.       g->piece = no_piece;
  1207.       g->color = side;
  1208.       (void) castle (side, f, t, 1);
  1209.       Game50 = GameCnt;
  1210.     }
  1211.   else
  1212.     {
  1213.       if (!(node->flags & capture) && (board[f] != pawn))
  1214.     rpthash[side][hashkey & 0xFF]++;
  1215.       else
  1216.     Game50 = GameCnt;
  1217.       *tempsf = svalue[f];
  1218.       *tempst = svalue[t];
  1219.       g->piece = *tempb = board[t];
  1220.       g->color = *tempc = color[t];
  1221.       if (*tempc != neutral)
  1222.     {
  1223.       UpdatePieceList (*tempc, t, 1);
  1224.       /* if capture decrement pawn count */
  1225.       if (*tempb == pawn)
  1226.         {
  1227.           --PawnCnt[*tempc][column (t)];
  1228.         }
  1229.       if (board[f] == pawn)
  1230.         {
  1231.           cf = column (f);
  1232.           ct = column (t);
  1233.           /* move count from from to to */
  1234.           --PawnCnt[side][cf];
  1235.           ++PawnCnt[side][ct];
  1236.  
  1237.           /*
  1238.                * calculate increment for pawn structure changes
  1239.                */
  1240.           /* doubled or more - */
  1241.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1242.         *INCscore -= 15;
  1243.           /* went to empty column + */
  1244.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1245.         *INCscore += 15;
  1246.  
  1247.           /*
  1248.                * went to outside col or empty col on one side ????????
  1249.                */
  1250.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1251.         *INCscore -= 15;
  1252.         }
  1253.       mtl[xside] -= value[*tempb];
  1254.       if (*tempb == pawn)
  1255.         pmtl[xside] -= valueP;
  1256.       UpdateHashbd (xside, *tempb, -1, t);
  1257.       *INCscore += *tempst;
  1258.       Mvboard[t]++;
  1259.     }
  1260.       color[t] = color[f];
  1261.       board[t] = board[f];
  1262.       svalue[t] = svalue[f];
  1263.       Pindex[t] = Pindex[f];
  1264.       PieceList[side][Pindex[t]] = t;
  1265.       color[f] = neutral;
  1266.       board[f] = no_piece;
  1267.       if (board[t] == pawn)
  1268.     if (t - f == 16)
  1269.       epsquare = f + 8;
  1270.     else if (f - t == 16)
  1271.       epsquare = f - 8;
  1272.       if (node->flags & promote)
  1273.     {
  1274.       board[t] = node->flags & pmask;
  1275.       if (board[t] == queen)
  1276.         HasQueen[side]++;
  1277.       else if (board[t] == rook)
  1278.         HasRook[side]++;
  1279.       else if (board[t] == bishop)
  1280.         HasBishop[side]++;
  1281.       else if (board[t] == knight)
  1282.         HasKnight[side]++;
  1283.       --PawnCnt[side][column (t)];
  1284.       mtl[side] += value[board[t]] - valueP;
  1285.       pmtl[side] -= valueP;
  1286.       UpdateHashbd (side, pawn, f, -1);
  1287.       UpdateHashbd (side, board[t], f, -1);
  1288.       *INCscore -= *tempsf;
  1289.     }
  1290.       if (node->flags & epmask)
  1291.     EnPassant (xside, f, t, 1);
  1292.       else
  1293.     UpdateHashbd (side, board[t], f, t);
  1294.       Mvboard[f]++;
  1295.     }
  1296. }
  1297.  
  1298. void
  1299. UnmakeMove (short int side,
  1300.         struct leaf * node,
  1301.         short int *tempb,
  1302.         short int *tempc,
  1303.         short int *tempsf,
  1304.         short int *tempst)
  1305.  
  1306. /*
  1307.  * Take back a move.
  1308.  */
  1309.  
  1310. {
  1311.   register short f, t, xside;
  1312.  
  1313.   xside = side ^ 1;
  1314.   f = node->f;
  1315.   t = node->t;
  1316.   epsquare = -1;
  1317.   Game50 = GameList[GameCnt--].Game50;
  1318.   if (node->flags & cstlmask)
  1319.     (void) castle (side, f, t, 2);
  1320.   else
  1321.     {
  1322.       color[f] = color[t];
  1323.       board[f] = board[t];
  1324.       svalue[f] = *tempsf;
  1325.       Pindex[f] = Pindex[t];
  1326.       PieceList[side][Pindex[f]] = f;
  1327.       color[t] = *tempc;
  1328.       board[t] = *tempb;
  1329.       svalue[t] = *tempst;
  1330.       if (node->flags & promote)
  1331.     {
  1332.       board[f] = pawn;
  1333.       ++PawnCnt[side][column (t)];
  1334.       mtl[side] += valueP - value[node->flags & pmask];
  1335.       pmtl[side] += valueP;
  1336.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1337.       UpdateHashbd (side, pawn, -1, t);
  1338.     }
  1339.       if (*tempc != neutral)
  1340.     {
  1341.       UpdatePieceList (*tempc, t, 2);
  1342.       if (*tempb == pawn)
  1343.         {
  1344.           ++PawnCnt[*tempc][column (t)];
  1345.         }
  1346.       if (board[f] == pawn)
  1347.         {
  1348.           --PawnCnt[side][column (t)];
  1349.           ++PawnCnt[side][column (f)];
  1350.         }
  1351.       mtl[xside] += value[*tempb];
  1352.       if (*tempb == pawn)
  1353.         pmtl[xside] += valueP;
  1354.       UpdateHashbd (xside, *tempb, -1, t);
  1355.       Mvboard[t]--;
  1356.     }
  1357.       if (node->flags & epmask)
  1358.     EnPassant (xside, f, t, 2);
  1359.       else
  1360.     UpdateHashbd (side, board[f], f, t);
  1361.       Mvboard[f]--;
  1362.       if (!(node->flags & capture) && (board[f] != pawn))
  1363.     rpthash[side][hashkey & 0xFF]--;
  1364.     }
  1365. }
  1366.  
  1367.  
  1368. void
  1369. InitializeStats (void)
  1370.  
  1371. /*
  1372.  * Scan thru the board seeing what's on each square. If a piece is found,
  1373.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1374.  * determine the material for each side and set the hashkey and hashbd
  1375.  * variables to represent the current board position. Array
  1376.  * PieceList[side][indx] contains the location of all the pieces of either
  1377.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1378.  * square.
  1379.  */
  1380.  
  1381. {
  1382.   register short i, sq;
  1383.  
  1384.   epsquare = -1;
  1385.   for (i = 0; i < 8; i++)
  1386.     {
  1387.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1388.     }
  1389.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1390.   PieceCnt[white] = PieceCnt[black] = 0;
  1391.   hashbd = hashkey = 0;
  1392.   for (sq = 0; sq < 64; sq++)
  1393.     if (color[sq] != neutral)
  1394.       {
  1395.     mtl[color[sq]] += value[board[sq]];
  1396.     if (board[sq] == pawn)
  1397.       {
  1398.         pmtl[color[sq]] += valueP;
  1399.         ++PawnCnt[color[sq]][column (sq)];
  1400.       }
  1401.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1402.  
  1403.     PieceList[color[sq]][Pindex[sq]] = sq;
  1404.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1405.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1406.       }
  1407. }
  1408.